{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "J5f3jlphTEF5"
      },
      "source": [
        "**Hyperparameter Tuning of CNN Architectures with Genetic Algorithm**"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "phFI2JzDyCy6"
      },
      "source": [
        "**Import Libraries**"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "0wJFA3MyAUCo"
      },
      "outputs": [],
      "source": [
        "import os\n",
        "from keras.preprocessing.image import  ImageDataGenerator\n",
        "from keras.layers import Dense,Flatten,GlobalAveragePooling2D,Input,Conv2D,MaxPooling2D,Dropout\n",
        "from keras.models import Model,load_model,Sequential\n",
        "from keras.callbacks import EarlyStopping"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "712Ltlo6yIQP"
      },
      "source": [
        "**Load Train and Test Dataset**"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "XfNWgacUzrPb",
        "outputId": "845cd3f0-0578-450f-90fe-e55a927784a4"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Found 5369 images belonging to 15 classes.\n",
            "Found 1342 images belonging to 15 classes.\n"
          ]
        }
      ],
      "source": [
        "#generate training and test images\n",
        "TARGET_SIZE=(224,224)\n",
        "INPUT_SIZE=(224,224,3)\n",
        "BATCHSIZE=32\t#could try 128 or 32\n",
        "\n",
        "#Normalization\n",
        "train_datagen = ImageDataGenerator(rescale=1./255)\n",
        "\n",
        "test_datagen = ImageDataGenerator(rescale=1./255)\n",
        "\n",
        "train_generator = train_datagen.flow_from_directory(\n",
        "        '/content/drive/MyDrive/Transfer_IDS_IIoT/Datasets/train_A',\n",
        "        target_size=TARGET_SIZE,\n",
        "        batch_size=BATCHSIZE,\n",
        "        class_mode='categorical')\n",
        "validation_generator = test_datagen.flow_from_directory(\n",
        "        '/content/drive/MyDrive/Transfer_IDS_IIoT/Datasets/test_A',\n",
        "        target_size=TARGET_SIZE,\n",
        "        batch_size=BATCHSIZE,\n",
        "        class_mode='categorical')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Bai1UAPYyP5X"
      },
      "source": [
        "**Define Input Shape and Number of Classes**"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "xaJc_5h2UmMD"
      },
      "outputs": [],
      "source": [
        "input_shape=INPUT_SIZE\n",
        "num_class=15\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "inaE3kZeyq4n"
      },
      "source": [
        "**Tuning of Generic CNN Model**"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "uyeenrHavJe1"
      },
      "outputs": [],
      "source": [
        "#Hyperparameters\n",
        "# f1,f2,f3 : Filter Sizes\n",
        "# k : kernel_size\n",
        "# a1, a2: activation functions\n",
        "# d1: drop out\n",
        "# op: optimizer\n",
        "# ep: number of epochs\n",
        "\n",
        "def CNN_model( f1, f2, f3, k, a1, a2, d1, op, ep):\n",
        "  model = Sequential()\n",
        "  model.add(Conv2D(filters = f1, kernel_size = (k, k), strides=(1,1), input_shape=input_shape,padding='same',activation=a1))\n",
        "  model.add(Conv2D(filters = f1, kernel_size = (k, k), strides=(1,1), padding='same',activation=a1))\n",
        "  model.add(MaxPooling2D(pool_size=(2,2)))\n",
        "  model.add(Conv2D(filters = f2, kernel_size = (k, k), strides=(1,1),padding='same',activation = a2))\n",
        "  model.add(Conv2D(filters = f2, kernel_size = (k, k), strides=(1,1),padding='same',activation = a2))\n",
        "  model.add(GlobalAveragePooling2D())\n",
        "  model.add(Dense(units = f3, activation = a2))\n",
        "  model.add(Dropout(rate=d1))\n",
        "  model.add(Dense(num_class,activation='softmax'))\n",
        "  model.compile(loss='categorical_crossentropy',optimizer=op,metrics=['accuracy'])\n",
        "  es = EarlyStopping(monitor=\"val_accuracy\", patience = 5)\n",
        "  model.fit(train_generator,steps_per_epoch=len(train_generator),epochs=ep,validation_data=validation_generator,\n",
        "            validation_steps=len(validation_generator), callbacks=[es], verbose=0)\n",
        "  return model"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "aZpPIMjPaR1S"
      },
      "outputs": [],
      "source": [
        "from random import choice\n",
        "from random import uniform\n",
        "from numpy.random import randint"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "A6ThPhZ-aULy"
      },
      "outputs": [],
      "source": [
        "def initialization_cnn():  \n",
        "  parameters = {}\n",
        "  f1 = choice([32, 64])\n",
        "  parameters[\"f1\"] = f1\n",
        "  f2 = choice([64, 128])\n",
        "  parameters[\"f2\"] = f2\n",
        "  f3 = choice([128, 256])\n",
        "  parameters[\"f3\"] = f3\n",
        "  k = choice([3,5])\n",
        "  parameters[\"k\"] = k\n",
        "  a1 = choice([\"relu\", \"selu\", \"elu\"])\n",
        "  parameters[\"a1\"] = a1\n",
        "  a2 = choice([\"relu\", \"selu\", \"elu\"])\n",
        "  parameters[\"a2\"] = a2\n",
        "  d1 = round(uniform(0.1, 0.6), 1)\n",
        "  parameters[\"d1\"] = d1\n",
        "  op = choice([\"adam\", \"nadam\", \"adamax\", \"adagrad\"])\n",
        "  parameters[\"op\"] = op\n",
        "  ep = randint(10, 25)\n",
        "  parameters[\"ep\"] = ep\n",
        "  return parameters"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "mXk316Y5aWuS"
      },
      "outputs": [],
      "source": [
        "def generate_population_cnn(n):\n",
        "  population = []\n",
        "  for i in range(n):\n",
        "    chromosome = initialization_cnn()\n",
        "    population.append(chromosome)\n",
        "  return population"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "GThv9LarabFR"
      },
      "outputs": [],
      "source": [
        "# Fitness evaluation metric: Classification Accuracy \n",
        "def fitness_evaluation(model):\n",
        "  metrics = model.evaluate(validation_generator)\n",
        "  return metrics[1]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "yotAr5nNacAj"
      },
      "outputs": [],
      "source": [
        "# Roulette wheel selection method\n",
        "def selection(population_fitness):\n",
        "  total = sum(population_fitness)\n",
        "  percentage = [round((x/total) * 100) for x in population_fitness]\n",
        "  selection_wheel = []\n",
        "  for pop_index,num in enumerate(percentage):\n",
        "    selection_wheel.extend([pop_index]*num)\n",
        "  parent1_ind = choice(selection_wheel)\n",
        "  parent2_ind = choice(selection_wheel)\n",
        "  return [parent1_ind, parent2_ind]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "eGOEmvhLagv7"
      },
      "outputs": [],
      "source": [
        "def crossover_cnn(parent1, parent2):\n",
        "  child1 = {}\n",
        "  child2 = {}\n",
        "\n",
        "  child1[\"f1\"] = choice([parent1[\"f1\"], parent2[\"f1\"]])\n",
        "  child1[\"f2\"] = choice([parent1[\"f2\"], parent2[\"f2\"]])\n",
        "  child1[\"f3\"] = choice([parent1[\"f3\"], parent2[\"f3\"]])\n",
        "\n",
        "  child2[\"f1\"] = choice([parent1[\"f1\"], parent2[\"f1\"]])\n",
        "  child2[\"f2\"] = choice([parent1[\"f2\"], parent2[\"f2\"]])\n",
        "  child2[\"f3\"] = choice([parent1[\"f3\"], parent2[\"f3\"]])\n",
        "\n",
        "  child1[\"k\"] = choice([parent1[\"k\"], parent2[\"k\"]])\n",
        "  child2[\"k\"] = choice([parent1[\"k\"], parent2[\"k\"]])\n",
        "\n",
        "  child1[\"a1\"] = parent1[\"a2\"]\n",
        "  child2[\"a1\"] = parent2[\"a2\"]\n",
        "\n",
        "  child1[\"a2\"] = parent2[\"a1\"]\n",
        "  child2[\"a2\"] = parent1[\"a1\"]\n",
        "\n",
        "  child1[\"d1\"] = parent1[\"d1\"]\n",
        "  child2[\"d1\"] = parent2[\"d1\"]\n",
        "\n",
        "  child1[\"op\"] = parent2[\"op\"]\n",
        "  child2[\"op\"] = parent1[\"op\"]\n",
        "\n",
        "  child1[\"ep\"] = parent1[\"ep\"]\n",
        "  child2[\"ep\"] = parent2[\"ep\"]\n",
        "  return [child1, child2]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "qkXn_EK0amGR"
      },
      "outputs": [],
      "source": [
        "def mutation_cnn(chromosome):\n",
        "  flag = randint(0,40)\n",
        "  if flag <= 20:\n",
        "    chromosome[\"ep\"] += randint(0, 10)\n",
        "  return chromosome"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "K7ZZHQHaaFlb",
        "outputId": "ecd1f380-7ab9-474e-892a-5b1de8834582"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "42/42 [==============================] - 9s 213ms/step - loss: 1.3277 - accuracy: 0.7004\n",
            "Parameters:  {'f1': 32, 'f2': 128, 'f3': 128, 'k': 5, 'a1': 'selu', 'a2': 'relu', 'd1': 0.3, 'op': 'nadam', 'ep': 15}\n",
            "Accuracy:  0.70045\n",
            "42/42 [==============================] - 11s 254ms/step - loss: 0.0285 - accuracy: 0.9933\n",
            "Parameters:  {'f1': 32, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'selu', 'a2': 'selu', 'd1': 0.4, 'op': 'adam', 'ep': 19}\n",
            "Accuracy:  0.99329\n",
            "42/42 [==============================] - 7s 157ms/step - loss: 0.0297 - accuracy: 0.9888\n",
            "Parameters:  {'f1': 64, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'relu', 'a2': 'relu', 'd1': 0.1, 'op': 'nadam', 'ep': 17}\n",
            "Accuracy:  0.98882\n",
            "42/42 [==============================] - 7s 160ms/step - loss: 1.2667 - accuracy: 0.7004\n",
            "Parameters:  {'f1': 64, 'f2': 64, 'f3': 128, 'k': 3, 'a1': 'elu', 'a2': 'elu', 'd1': 0.3, 'op': 'adagrad', 'ep': 11}\n",
            "Accuracy:  0.70045\n",
            "42/42 [==============================] - 8s 197ms/step - loss: 0.1755 - accuracy: 0.9396\n",
            "Parameters:  {'f1': 32, 'f2': 128, 'f3': 256, 'k': 3, 'a1': 'selu', 'a2': 'relu', 'd1': 0.5, 'op': 'adamax', 'ep': 10}\n",
            "Accuracy:  0.93964\n",
            "Generation  1  Outcome: \n",
            "Maximum accuracy in generation 1 : 0.9932935833930969\n",
            "42/42 [==============================] - 7s 170ms/step - loss: 0.0177 - accuracy: 0.9933\n",
            "Parameters:  {'f1': 64, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'relu', 'a2': 'relu', 'd1': 0.1, 'op': 'nadam', 'ep': 17}\n",
            "Accuracy:  0.99329\n",
            "42/42 [==============================] - 5s 111ms/step - loss: 1.2551 - accuracy: 0.7004\n",
            "Parameters:  {'f1': 64, 'f2': 64, 'f3': 128, 'k': 3, 'a1': 'elu', 'a2': 'elu', 'd1': 0.3, 'op': 'adagrad', 'ep': 11}\n",
            "Accuracy:  0.70045\n",
            "42/42 [==============================] - 5s 112ms/step - loss: 0.1629 - accuracy: 0.9292\n",
            "Parameters:  {'f1': 32, 'f2': 128, 'f3': 256, 'k': 3, 'a1': 'selu', 'a2': 'relu', 'd1': 0.5, 'op': 'adamax', 'ep': 10}\n",
            "Accuracy:  0.92921\n",
            "42/42 [==============================] - 5s 110ms/step - loss: 0.0059 - accuracy: 0.9985\n",
            "Parameters:  {'f1': 32, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'relu', 'a2': 'selu', 'd1': 0.1, 'op': 'adam', 'ep': 17}\n",
            "Accuracy:  0.99851\n",
            "42/42 [==============================] - 5s 126ms/step - loss: 0.0142 - accuracy: 0.9918\n",
            "Parameters:  {'f1': 64, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'selu', 'a2': 'relu', 'd1': 0.4, 'op': 'nadam', 'ep': 19}\n",
            "Accuracy:  0.9918\n",
            "Generation  2  Outcome: \n",
            "Maximum accuracy in generation 2 : 0.9985097050666809\n",
            "42/42 [==============================] - 5s 124ms/step - loss: 0.1869 - accuracy: 0.9419\n",
            "Parameters:  {'f1': 64, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'relu', 'a2': 'relu', 'd1': 0.1, 'op': 'nadam', 'ep': 17}\n",
            "Accuracy:  0.94188\n",
            "42/42 [==============================] - 5s 117ms/step - loss: 0.0083 - accuracy: 0.9978\n",
            "Parameters:  {'f1': 32, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'relu', 'a2': 'selu', 'd1': 0.1, 'op': 'adam', 'ep': 17}\n",
            "Accuracy:  0.99776\n",
            "42/42 [==============================] - 5s 119ms/step - loss: 0.7228 - accuracy: 0.7683\n",
            "Parameters:  {'f1': 64, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'selu', 'a2': 'relu', 'd1': 0.4, 'op': 'nadam', 'ep': 19}\n",
            "Accuracy:  0.76826\n",
            "42/42 [==============================] - 5s 118ms/step - loss: 1.9231 - accuracy: 0.7683\n",
            "Parameters:  {'f1': 64, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'relu', 'a2': 'selu', 'd1': 0.1, 'op': 'nadam', 'ep': 17}\n",
            "Accuracy:  0.76826\n",
            "42/42 [==============================] - 5s 114ms/step - loss: 0.0075 - accuracy: 0.9963\n",
            "Parameters:  {'f1': 64, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'relu', 'a2': 'relu', 'd1': 0.4, 'op': 'nadam', 'ep': 19}\n",
            "Accuracy:  0.99627\n",
            "Generation  3  Outcome: \n",
            "Maximum accuracy in generation 3 : 0.997764527797699\n",
            "42/42 [==============================] - 5s 117ms/step - loss: 0.0540 - accuracy: 0.9642\n",
            "Parameters:  {'f1': 64, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'relu', 'a2': 'relu', 'd1': 0.1, 'op': 'nadam', 'ep': 17}\n",
            "Accuracy:  0.96423\n",
            "42/42 [==============================] - 5s 115ms/step - loss: 0.0081 - accuracy: 0.9963\n",
            "Parameters:  {'f1': 32, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'relu', 'a2': 'selu', 'd1': 0.1, 'op': 'adam', 'ep': 17}\n",
            "Accuracy:  0.99627\n",
            "42/42 [==============================] - 5s 119ms/step - loss: 0.0750 - accuracy: 0.9858\n",
            "Parameters:  {'f1': 64, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'relu', 'a2': 'relu', 'd1': 0.4, 'op': 'nadam', 'ep': 19}\n",
            "Accuracy:  0.98584\n",
            "42/42 [==============================] - 5s 124ms/step - loss: 0.0493 - accuracy: 0.9680\n",
            "Parameters:  {'f1': 64, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'selu', 'a2': 'relu', 'd1': 0.1, 'op': 'nadam', 'ep': 17}\n",
            "Accuracy:  0.96796\n",
            "42/42 [==============================] - 5s 119ms/step - loss: 0.0073 - accuracy: 0.9970\n",
            "Parameters:  {'f1': 64, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'relu', 'a2': 'relu', 'd1': 0.1, 'op': 'adam', 'ep': 25}\n",
            "Accuracy:  0.99702\n",
            "Generation  4  Outcome: \n",
            "Maximum accuracy in generation 4 : 0.997019350528717\n",
            "42/42 [==============================] - 5s 122ms/step - loss: 0.0129 - accuracy: 0.9940\n",
            "Parameters:  {'f1': 64, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'relu', 'a2': 'relu', 'd1': 0.4, 'op': 'nadam', 'ep': 19}\n",
            "Accuracy:  0.99404\n",
            "42/42 [==============================] - 5s 122ms/step - loss: 0.0152 - accuracy: 0.9925\n",
            "Parameters:  {'f1': 64, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'selu', 'a2': 'relu', 'd1': 0.1, 'op': 'nadam', 'ep': 17}\n",
            "Accuracy:  0.99255\n",
            "42/42 [==============================] - 5s 117ms/step - loss: 0.0077 - accuracy: 0.9963\n",
            "Parameters:  {'f1': 64, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'relu', 'a2': 'relu', 'd1': 0.1, 'op': 'adam', 'ep': 25}\n",
            "Accuracy:  0.99627\n",
            "42/42 [==============================] - 5s 123ms/step - loss: 0.0837 - accuracy: 0.9627\n",
            "Parameters:  {'f1': 64, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'selu', 'a2': 'relu', 'd1': 0.1, 'op': 'nadam', 'ep': 17}\n",
            "Accuracy:  0.96274\n",
            "42/42 [==============================] - 5s 118ms/step - loss: 0.0078 - accuracy: 0.9978\n",
            "Parameters:  {'f1': 32, 'f2': 128, 'f3': 256, 'k': 5, 'a1': 'relu', 'a2': 'relu', 'd1': 0.4, 'op': 'adam', 'ep': 19}\n",
            "Accuracy:  0.99776\n",
            "Generation  5  Outcome: \n",
            "Maximum accuracy in generation 5 : 0.997764527797699\n"
          ]
        }
      ],
      "source": [
        "generations = 5\n",
        "threshold = 90\n",
        "num_pop = 5\n",
        "\n",
        "population = generate_population_cnn(num_pop)\n",
        "\n",
        "for generation in range(generations):\n",
        "\n",
        "  population_fitness = []\n",
        "  for chromosome in population:\n",
        "    f1 = chromosome[\"f1\"]\n",
        "    f2 = chromosome[\"f2\"]\n",
        "    f3 = chromosome[\"f3\"]\n",
        "    k = chromosome[\"k\"]\n",
        "    a1 = chromosome[\"a1\"]\n",
        "    a2 = chromosome[\"a2\"]\n",
        "    d1 = chromosome[\"d1\"]\n",
        "    op = chromosome[\"op\"]\n",
        "    ep = chromosome[\"ep\"]\n",
        "\n",
        "    try:\n",
        "      model = CNN_model(f1, f2, f3, k, a1, a2, d1, op, ep)\n",
        "      acc = fitness_evaluation(model)\n",
        "      print(\"Parameters: \", chromosome)\n",
        "      print(\"Accuracy: \", round(acc,5))\n",
        "    except:\n",
        "      acc=0\n",
        "      print(\"Parameters: \", chromosome)\n",
        "      print(\"Invalid parameters - Build fail\")\n",
        "\n",
        "    population_fitness.append(acc)\n",
        "    \n",
        "  parents_ind = selection(population_fitness)\n",
        "  parent1 = population[parents_ind[0]]\n",
        "  parent2 = population[parents_ind[1]]\n",
        "\n",
        "  children = crossover_cnn(parent1, parent2)\n",
        "  child1 = mutation_cnn(children[0])\n",
        "  child2 = mutation_cnn(children[1])\n",
        "\n",
        "  population.append(child1)\n",
        "  population.append(child2)\n",
        "\n",
        "  print(\"Generation \", generation+1,\" Outcome: \")\n",
        "  if max(population_fitness) >= threshold:\n",
        "    print(\"Obtained desired accuracy: \", max(population_fitness))\n",
        "    break\n",
        "  else:\n",
        "    print(\"Maximum accuracy in generation {} : {}\".format(generation+1, max(population_fitness)))\n",
        "\n",
        "  first_min = min(population_fitness)\n",
        "  first_min_ind = population_fitness.index(first_min)\n",
        "  population.remove(population[first_min_ind])\n",
        "  second_min = min(population_fitness)\n",
        "  second_min_ind = population_fitness.index(second_min)\n",
        "  population.remove(population[second_min_ind])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ljLHw3mLGCge"
      },
      "source": [
        "**Tuning of Xception Model**"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "EBiJOupxj-Ww"
      },
      "outputs": [],
      "source": [
        "from keras.applications.xception import  Xception"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "JbO1Tsm6S-FR"
      },
      "outputs": [],
      "source": [
        "#Hyperparameters\n",
        "# frozen: Frozen layers\n",
        "# f1: Number of units in dense layer\n",
        "# a1: Activation functions\n",
        "# d1: Drop out\n",
        "# op: Optimizer\n",
        "# ep: Number of epochs\n",
        "\n",
        "#Define Xception Model\n",
        "def Xception_model(frozen, f1, a1, d1, op, ep):\n",
        "  model_fine_tune = Xception(include_top=False, weights='imagenet', input_shape=input_shape)\n",
        "  for layer in model_fine_tune.layers[:frozen]:           #125\n",
        "      layer.trainable = False\n",
        "  for layer in model_fine_tune.layers[frozen:]:\n",
        "      layer.trainable = True\n",
        "  model = GlobalAveragePooling2D()(model_fine_tune.output)\n",
        "  model=Dense(units=f1,activation=a1)(model)        #256\n",
        "  model=Dropout(d1)(model)                             #0.4\n",
        "  model = Dense(num_class, activation='softmax')(model)\n",
        "  model = Model(model_fine_tune.input, model, name='xception')\n",
        "  model.compile(loss='categorical_crossentropy',optimizer=op,metrics=['accuracy'])\n",
        "  es = EarlyStopping(monitor=\"val_accuracy\", patience = 2)\n",
        "  model.fit(train_generator,steps_per_epoch=len(train_generator),epochs=ep,validation_data=validation_generator,\n",
        "            validation_steps=len(validation_generator), callbacks=[es], verbose=0)\n",
        "  return model"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "zogKssXXS-FS"
      },
      "outputs": [],
      "source": [
        "from random import choice\n",
        "from random import uniform\n",
        "from numpy.random import randint"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "zKwFcoUNS-FS"
      },
      "outputs": [],
      "source": [
        "def initialization_xception():  \n",
        "  parameters = {}\n",
        "  frozen = choice(range(100, 150, 1))\n",
        "  parameters[\"frozen\"] = frozen\n",
        "  f1 = choice([128, 256])\n",
        "  parameters[\"f1\"] = f1\n",
        "  a1 = choice([\"relu\", \"selu\", \"elu\"])\n",
        "  parameters[\"a1\"] = a1\n",
        "  d1 = round(uniform(0.1, 0.6), 1)\n",
        "  parameters[\"d1\"] = d1\n",
        "  op = choice([\"adam\", \"nadam\", \"adamax\", \"adagrad\"])\n",
        "  parameters[\"op\"] = op\n",
        "  ep = randint(10, 25)\n",
        "  parameters[\"ep\"] = ep\n",
        "  return parameters"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "EwXGBK93S-FS"
      },
      "outputs": [],
      "source": [
        "def generate_population_xception(n):\n",
        "  population = []\n",
        "  for i in range(n):\n",
        "    chromosome = initialization_xception()\n",
        "    population.append(chromosome)\n",
        "  return population"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "bR2pdAXCS-FT"
      },
      "outputs": [],
      "source": [
        "# Fitness evaluation metric: Classification Accuracy \n",
        "def fitness_evaluation(model):\n",
        "  metrics = model.evaluate(validation_generator)\n",
        "  return metrics[1]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "wnivslBaS-FT"
      },
      "outputs": [],
      "source": [
        "# Roulette wheel selection method\n",
        "def selection(population_fitness):\n",
        "  total = sum(population_fitness)\n",
        "  percentage = [round((x/total) * 100) for x in population_fitness]\n",
        "  selection_wheel = []\n",
        "  for pop_index,num in enumerate(percentage):\n",
        "    selection_wheel.extend([pop_index]*num)\n",
        "  parent1_ind = choice(selection_wheel)\n",
        "  parent2_ind = choice(selection_wheel)\n",
        "  return [parent1_ind, parent2_ind]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "1eMH52rRS-FT"
      },
      "outputs": [],
      "source": [
        "def crossover_xception(parent1, parent2):\n",
        "  child1 = {}\n",
        "  child2 = {}\n",
        "\n",
        "  child1[\"frozen\"] = choice([parent1[\"frozen\"], parent2[\"frozen\"]])\n",
        "  child2[\"frozen\"] = choice([parent1[\"frozen\"], parent2[\"frozen\"]])\n",
        "\n",
        "  child1[\"f1\"] = choice([parent1[\"f1\"], parent2[\"f1\"]])\n",
        "  child2[\"f1\"] = choice([parent1[\"f1\"], parent2[\"f1\"]])\n",
        "\n",
        "  child1[\"a1\"] = parent2[\"a1\"]\n",
        "  child2[\"a1\"] = parent1[\"a1\"]\n",
        "\n",
        "  child1[\"d1\"] = parent1[\"d1\"]\n",
        "  child2[\"d1\"] = parent2[\"d1\"]\n",
        "\n",
        "  child1[\"op\"] = parent1[\"op\"]\n",
        "  child2[\"op\"] = parent2[\"op\"]\n",
        "\n",
        "  child1[\"ep\"] = parent1[\"ep\"]\n",
        "  child2[\"ep\"] = parent2[\"ep\"]\n",
        "  return [child1, child2]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "vFliidOZS-FT"
      },
      "outputs": [],
      "source": [
        "def mutation_xception(chromosome):\n",
        "  flag = randint(0,40)\n",
        "  if flag <= 20:\n",
        "    chromosome[\"ep\"] += randint(0, 10)\n",
        "  return chromosome"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "BIH0dop6S-FT",
        "outputId": "44b4b651-80b0-4832-85c1-fad97478a7ad"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "42/42 [==============================] - 6s 134ms/step - loss: 0.0304 - accuracy: 0.9888\n",
            "Parameters:  {'frozen': 149, 'f1': 256, 'a1': 'selu', 'd1': 0.2, 'op': 'adamax', 'ep': 16}\n",
            "Accuracy:  0.98882\n",
            "42/42 [==============================] - 6s 135ms/step - loss: 0.0522 - accuracy: 0.9806\n",
            "Parameters:  {'frozen': 143, 'f1': 256, 'a1': 'elu', 'd1': 0.3, 'op': 'adam', 'ep': 16}\n",
            "Accuracy:  0.98063\n",
            "42/42 [==============================] - 6s 134ms/step - loss: 0.0226 - accuracy: 0.9903\n",
            "Parameters:  {'frozen': 128, 'f1': 128, 'a1': 'selu', 'd1': 0.2, 'op': 'adamax', 'ep': 14}\n",
            "Accuracy:  0.99031\n",
            "Generation  1  Outcome: \n",
            "Maximum accuracy in generation 1 : 0.9903129935264587\n",
            "42/42 [==============================] - 6s 135ms/step - loss: 0.0338 - accuracy: 0.9888\n",
            "Parameters:  {'frozen': 149, 'f1': 256, 'a1': 'selu', 'd1': 0.2, 'op': 'adamax', 'ep': 16}\n",
            "Accuracy:  0.98882\n",
            "42/42 [==============================] - 6s 135ms/step - loss: 0.0631 - accuracy: 0.9784\n",
            "Parameters:  {'frozen': 149, 'f1': 256, 'a1': 'elu', 'd1': 0.2, 'op': 'adamax', 'ep': 24}\n",
            "Accuracy:  0.97839\n",
            "42/42 [==============================] - 6s 134ms/step - loss: 0.0484 - accuracy: 0.9821\n",
            "Parameters:  {'frozen': 143, 'f1': 256, 'a1': 'selu', 'd1': 0.3, 'op': 'adam', 'ep': 16}\n",
            "Accuracy:  0.98212\n",
            "Generation  2  Outcome: \n",
            "Maximum accuracy in generation 2 : 0.9888226389884949\n",
            "42/42 [==============================] - 6s 134ms/step - loss: 0.0445 - accuracy: 0.9799\n",
            "Parameters:  {'frozen': 149, 'f1': 256, 'a1': 'selu', 'd1': 0.2, 'op': 'adamax', 'ep': 16}\n",
            "Accuracy:  0.97988\n",
            "42/42 [==============================] - 6s 135ms/step - loss: 0.0392 - accuracy: 0.9829\n",
            "Parameters:  {'frozen': 149, 'f1': 256, 'a1': 'elu', 'd1': 0.2, 'op': 'adamax', 'ep': 22}\n",
            "Accuracy:  0.98286\n",
            "42/42 [==============================] - 6s 135ms/step - loss: 0.0328 - accuracy: 0.9873\n",
            "Parameters:  {'frozen': 149, 'f1': 256, 'a1': 'selu', 'd1': 0.2, 'op': 'adamax', 'ep': 24}\n",
            "Accuracy:  0.98733\n",
            "Generation  3  Outcome: \n",
            "Maximum accuracy in generation 3 : 0.9873323440551758\n",
            "42/42 [==============================] - 6s 133ms/step - loss: 0.0379 - accuracy: 0.9858\n",
            "Parameters:  {'frozen': 149, 'f1': 256, 'a1': 'selu', 'd1': 0.2, 'op': 'adamax', 'ep': 24}\n",
            "Accuracy:  0.98584\n",
            "42/42 [==============================] - 6s 134ms/step - loss: 0.0591 - accuracy: 0.9776\n",
            "Parameters:  {'frozen': 149, 'f1': 256, 'a1': 'selu', 'd1': 0.2, 'op': 'adamax', 'ep': 24}\n",
            "Accuracy:  0.97765\n",
            "42/42 [==============================] - 6s 135ms/step - loss: 0.0330 - accuracy: 0.9873\n",
            "Parameters:  {'frozen': 149, 'f1': 256, 'a1': 'selu', 'd1': 0.2, 'op': 'adamax', 'ep': 21}\n",
            "Accuracy:  0.98733\n",
            "Generation  4  Outcome: \n",
            "Maximum accuracy in generation 4 : 0.9873323440551758\n",
            "42/42 [==============================] - 6s 134ms/step - loss: 0.0370 - accuracy: 0.9858\n",
            "Parameters:  {'frozen': 149, 'f1': 256, 'a1': 'selu', 'd1': 0.2, 'op': 'adamax', 'ep': 24}\n",
            "Accuracy:  0.98584\n",
            "42/42 [==============================] - 6s 135ms/step - loss: 0.0387 - accuracy: 0.9836\n",
            "Parameters:  {'frozen': 149, 'f1': 256, 'a1': 'selu', 'd1': 0.2, 'op': 'adamax', 'ep': 21}\n",
            "Accuracy:  0.98361\n",
            "42/42 [==============================] - 6s 135ms/step - loss: 0.0491 - accuracy: 0.9806\n",
            "Parameters:  {'frozen': 149, 'f1': 256, 'a1': 'selu', 'd1': 0.2, 'op': 'adamax', 'ep': 29}\n",
            "Accuracy:  0.98063\n",
            "Generation  5  Outcome: \n",
            "Maximum accuracy in generation 5 : 0.9858420491218567\n"
          ]
        }
      ],
      "source": [
        "generations = 5\n",
        "threshold = 90\n",
        "num_pop = 3\n",
        "\n",
        "population = generate_population_xception(num_pop)\n",
        "\n",
        "for generation in range(generations):\n",
        "\n",
        "  population_fitness = []\n",
        "  for chromosome in population:\n",
        "    frozen = chromosome[\"frozen\"]\n",
        "    f1 = chromosome[\"f1\"]\n",
        "    a1 = chromosome[\"a1\"]\n",
        "    d1 = chromosome[\"d1\"]\n",
        "    op = chromosome[\"op\"]\n",
        "    ep = chromosome[\"ep\"]\n",
        "\n",
        "    try:\n",
        "      model = Xception_model(frozen, f1, a1, d1, op, ep)\n",
        "      acc = fitness_evaluation(model)\n",
        "      print(\"Parameters: \", chromosome)\n",
        "      print(\"Accuracy: \", round(acc,5))\n",
        "    except:\n",
        "      acc=0\n",
        "      print(\"Parameters: \", chromosome)\n",
        "      print(\"Invalid parameters - Build fail\")\n",
        "\n",
        "    population_fitness.append(acc)\n",
        "    \n",
        "  parents_ind = selection(population_fitness)\n",
        "  parent1 = population[parents_ind[0]]\n",
        "  parent2 = population[parents_ind[1]]\n",
        "\n",
        "  children = crossover_xception(parent1, parent2)\n",
        "  child1 = mutation_xception(children[0])\n",
        "  child2 = mutation_xception(children[1])\n",
        "\n",
        "  population.append(child1)\n",
        "  population.append(child2)\n",
        "\n",
        "  print(\"Generation \", generation+1,\" Outcome: \")\n",
        "  if max(population_fitness) >= threshold:\n",
        "    print(\"Obtained desired accuracy: \", max(population_fitness))\n",
        "    break\n",
        "  else:\n",
        "    print(\"Maximum accuracy in generation {} : {}\".format(generation+1, max(population_fitness)))\n",
        "\n",
        "  first_min = min(population_fitness)\n",
        "  first_min_ind = population_fitness.index(first_min)\n",
        "  population.remove(population[first_min_ind])\n",
        "  second_min = min(population_fitness)\n",
        "  second_min_ind = population_fitness.index(second_min)\n",
        "  population.remove(population[second_min_ind])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "eEN14DxTUakI"
      },
      "source": [
        "**Tuning of VGG16 Model**"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ZxEAc5itUakJ"
      },
      "outputs": [],
      "source": [
        "from keras.applications.vgg16 import VGG16"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "XAXzM_RCUakJ"
      },
      "outputs": [],
      "source": [
        "#Hyperparameters\n",
        "# frozen: Frozen layers\n",
        "# f1: Number of units in dense layer\n",
        "# a1: Activation functions\n",
        "# d1: Drop out\n",
        "# op: Optimizer\n",
        "# ep: Number of epochs\n",
        "\n",
        "#Define VGG16 Model\n",
        "def VGG16_model(frozen, f1, a1, d1, op, ep):\n",
        "  model_fine_tune = VGG16(include_top=False, weights='imagenet', input_shape=input_shape)\n",
        "  for layer in model_fine_tune.layers[:frozen]:          \n",
        "      layer.trainable = False\n",
        "  for layer in model_fine_tune.layers[frozen:]:\n",
        "      layer.trainable = True\n",
        "  model = GlobalAveragePooling2D()(model_fine_tune.output)\n",
        "  model=Dense(units=f1,activation=a1)(model)       \n",
        "  model=Dropout(d1)(model)                             \n",
        "  model = Dense(num_class, activation='softmax')(model)\n",
        "  model = Model(model_fine_tune.input, model, name='vgg')\n",
        "  model.compile(loss='categorical_crossentropy',optimizer=op,metrics=['accuracy'])\n",
        "  es = EarlyStopping(monitor=\"val_accuracy\", patience = 4)\n",
        "  model.fit(train_generator,steps_per_epoch=len(train_generator),epochs=ep,validation_data=validation_generator,\n",
        "            validation_steps=len(validation_generator), callbacks=[es], verbose=0)\n",
        "  return model"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "1Fr_M6b6UakJ"
      },
      "outputs": [],
      "source": [
        "from random import choice\n",
        "from random import uniform\n",
        "from numpy.random import randint"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "cXhtWUduUakJ"
      },
      "outputs": [],
      "source": [
        "def initialization_vgg16():  \n",
        "  parameters = {}\n",
        "  #frozen = choice([8, 16, 24])\n",
        "  frozen = choice(range(8, 25, 1))\n",
        "  parameters[\"frozen\"] = frozen\n",
        "  f1 = choice([128, 256])\n",
        "  parameters[\"f1\"] = f1\n",
        "  a1 = choice([\"relu\", \"selu\", \"elu\"])\n",
        "  parameters[\"a1\"] = a1\n",
        "  d1 = round(uniform(0.1, 0.6), 1)\n",
        "  parameters[\"d1\"] = d1\n",
        "  op = choice([\"adam\", \"nadam\", \"adamax\", \"adagrad\"])\n",
        "  parameters[\"op\"] = op\n",
        "  ep = randint(10, 25)\n",
        "  parameters[\"ep\"] = ep\n",
        "  return parameters"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "aqk9MBESUakJ"
      },
      "outputs": [],
      "source": [
        "def generate_population_vgg16(n):\n",
        "  population = []\n",
        "  for i in range(n):\n",
        "    chromosome = initialization_vgg16()\n",
        "    population.append(chromosome)\n",
        "  return population"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "0Torx3q5UakJ"
      },
      "outputs": [],
      "source": [
        "# Fitness evaluation metric: Classification Accuracy \n",
        "def fitness_evaluation(model):\n",
        "  metrics = model.evaluate(validation_generator)\n",
        "  return metrics[1]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "qHitBxAMUakK"
      },
      "outputs": [],
      "source": [
        "# Roulette wheel selection method\n",
        "def selection(population_fitness):\n",
        "  total = sum(population_fitness)\n",
        "  percentage = [round((x/total) * 100) for x in population_fitness]\n",
        "  selection_wheel = []\n",
        "  for pop_index,num in enumerate(percentage):\n",
        "    selection_wheel.extend([pop_index]*num)\n",
        "  parent1_ind = choice(selection_wheel)\n",
        "  parent2_ind = choice(selection_wheel)\n",
        "  return [parent1_ind, parent2_ind]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "3Bg9N9XGUakK"
      },
      "outputs": [],
      "source": [
        "def crossover_vgg16(parent1, parent2):\n",
        "  child1 = {}\n",
        "  child2 = {}\n",
        "\n",
        "  child1[\"frozen\"] = choice([parent1[\"frozen\"], parent2[\"frozen\"]])\n",
        "  child2[\"frozen\"] = choice([parent1[\"frozen\"], parent2[\"frozen\"]])\n",
        "\n",
        "  child1[\"f1\"] = choice([parent1[\"f1\"], parent2[\"f1\"]])\n",
        "  child2[\"f1\"] = choice([parent1[\"f1\"], parent2[\"f1\"]])\n",
        "\n",
        "  child1[\"a1\"] = parent2[\"a1\"]\n",
        "  child2[\"a1\"] = parent1[\"a1\"]\n",
        "\n",
        "  child1[\"d1\"] = parent1[\"d1\"]\n",
        "  child2[\"d1\"] = parent2[\"d1\"]\n",
        "\n",
        "  child1[\"op\"] = parent1[\"op\"]\n",
        "  child2[\"op\"] = parent2[\"op\"]\n",
        "\n",
        "  child1[\"ep\"] = parent1[\"ep\"]\n",
        "  child2[\"ep\"] = parent2[\"ep\"]\n",
        "  return [child1, child2]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "yrOKMpLkUakK"
      },
      "outputs": [],
      "source": [
        "def mutation_vgg16(chromosome):\n",
        "  flag = randint(0,40)\n",
        "  if flag <= 20:\n",
        "    chromosome[\"ep\"] += randint(0, 10)\n",
        "  return chromosome"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "pHj19L7LUakK",
        "outputId": "3c58c347-9fce-480c-9a28-76d227abab03"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/vgg16/vgg16_weights_tf_dim_ordering_tf_kernels_notop.h5\n",
            "58889256/58889256 [==============================] - 0s 0us/step\n",
            "42/42 [==============================] - 7s 161ms/step - loss: 1.0452 - accuracy: 0.7004\n",
            "Parameters:  {'frozen': 23, 'f1': 128, 'a1': 'elu', 'd1': 0.2, 'op': 'adagrad', 'ep': 18}\n",
            "Accuracy:  0.70045\n",
            "42/42 [==============================] - 7s 163ms/step - loss: 0.0135 - accuracy: 0.9948\n",
            "Parameters:  {'frozen': 8, 'f1': 128, 'a1': 'elu', 'd1': 0.5, 'op': 'adagrad', 'ep': 11}\n",
            "Accuracy:  0.99478\n",
            "42/42 [==============================] - 7s 160ms/step - loss: 0.7706 - accuracy: 0.7683\n",
            "Parameters:  {'frozen': 12, 'f1': 128, 'a1': 'relu', 'd1': 0.5, 'op': 'nadam', 'ep': 24}\n",
            "Accuracy:  0.76826\n",
            "42/42 [==============================] - 7s 162ms/step - loss: 0.0221 - accuracy: 0.9903\n",
            "Parameters:  {'frozen': 16, 'f1': 128, 'a1': 'relu', 'd1': 0.4, 'op': 'adamax', 'ep': 24}\n",
            "Accuracy:  0.99031\n",
            "42/42 [==============================] - 7s 161ms/step - loss: 0.0305 - accuracy: 0.9896\n",
            "Parameters:  {'frozen': 17, 'f1': 256, 'a1': 'elu', 'd1': 0.5, 'op': 'adamax', 'ep': 20}\n",
            "Accuracy:  0.98957\n",
            "Generation  1  Outcome: \n",
            "Maximum accuracy in generation 1 : 0.994783878326416\n",
            "42/42 [==============================] - 7s 160ms/step - loss: 1.7987 - accuracy: 0.7004\n",
            "Parameters:  {'frozen': 12, 'f1': 128, 'a1': 'relu', 'd1': 0.5, 'op': 'nadam', 'ep': 24}\n",
            "Accuracy:  0.70045\n",
            "42/42 [==============================] - 7s 163ms/step - loss: 0.0090 - accuracy: 0.9963\n",
            "Parameters:  {'frozen': 16, 'f1': 128, 'a1': 'relu', 'd1': 0.4, 'op': 'adamax', 'ep': 24}\n",
            "Accuracy:  0.99627\n",
            "42/42 [==============================] - 7s 162ms/step - loss: 0.0176 - accuracy: 0.9948\n",
            "Parameters:  {'frozen': 17, 'f1': 256, 'a1': 'elu', 'd1': 0.5, 'op': 'adamax', 'ep': 20}\n",
            "Accuracy:  0.99478\n",
            "42/42 [==============================] - 7s 163ms/step - loss: 0.0104 - accuracy: 0.9955\n",
            "Parameters:  {'frozen': 8, 'f1': 128, 'a1': 'elu', 'd1': 0.5, 'op': 'adagrad', 'ep': 11}\n",
            "Accuracy:  0.99553\n",
            "42/42 [==============================] - 7s 161ms/step - loss: 0.0142 - accuracy: 0.9940\n",
            "Parameters:  {'frozen': 8, 'f1': 128, 'a1': 'elu', 'd1': 0.5, 'op': 'adamax', 'ep': 21}\n",
            "Accuracy:  0.99404\n",
            "Generation  2  Outcome: \n",
            "Maximum accuracy in generation 2 : 0.9962742328643799\n",
            "42/42 [==============================] - 7s 162ms/step - loss: 0.0230 - accuracy: 0.9896\n",
            "Parameters:  {'frozen': 17, 'f1': 256, 'a1': 'elu', 'd1': 0.5, 'op': 'adamax', 'ep': 20}\n",
            "Accuracy:  0.98957\n"
          ]
        }
      ],
      "source": [
        "generations = 5\n",
        "threshold = 90\n",
        "num_pop = 5\n",
        "\n",
        "population = generate_population_vgg16(num_pop)\n",
        "\n",
        "for generation in range(generations):\n",
        "\n",
        "  population_fitness = []\n",
        "  for chromosome in population:\n",
        "    frozen = chromosome[\"frozen\"]\n",
        "    f1 = chromosome[\"f1\"]\n",
        "    a1 = chromosome[\"a1\"]\n",
        "    d1 = chromosome[\"d1\"]\n",
        "    op = chromosome[\"op\"]\n",
        "    ep = chromosome[\"ep\"]\n",
        "\n",
        "    try:\n",
        "      model = VGG16_model(frozen, f1, a1, d1, op, ep)\n",
        "      acc = fitness_evaluation(model)\n",
        "      print(\"Parameters: \", chromosome)\n",
        "      print(\"Accuracy: \", round(acc,5))\n",
        "    except:\n",
        "      acc=0\n",
        "      print(\"Parameters: \", chromosome)\n",
        "      print(\"Invalid parameters - Build fail\")\n",
        "\n",
        "    population_fitness.append(acc)\n",
        "    \n",
        "  parents_ind = selection(population_fitness)\n",
        "  parent1 = population[parents_ind[0]]\n",
        "  parent2 = population[parents_ind[1]]\n",
        "\n",
        "  children = crossover_vgg16(parent1, parent2)\n",
        "  child1 = mutation_vgg16(children[0])\n",
        "  child2 = mutation_vgg16(children[1])\n",
        "\n",
        "  population.append(child1)\n",
        "  population.append(child2)\n",
        "\n",
        "  print(\"Generation \", generation+1,\" Outcome: \")\n",
        "  if max(population_fitness) >= threshold:\n",
        "    print(\"Obtained desired accuracy: \", max(population_fitness))\n",
        "    break\n",
        "  else:\n",
        "    print(\"Maximum accuracy in generation {} : {}\".format(generation+1, max(population_fitness)))\n",
        "\n",
        "  first_min = min(population_fitness)\n",
        "  first_min_ind = population_fitness.index(first_min)\n",
        "  population.remove(population[first_min_ind])\n",
        "  second_min = min(population_fitness)\n",
        "  second_min_ind = population_fitness.index(second_min)\n",
        "  population.remove(population[second_min_ind])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "pVpDnZjdq6RI"
      },
      "source": [
        "**Tuning of VGG19 Model**"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "HuAlDQhLq6RI"
      },
      "outputs": [],
      "source": [
        "from keras.applications.vgg19 import VGG19"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "OcP-NsKcq6RI"
      },
      "outputs": [],
      "source": [
        "#Hyperparameters\n",
        "# frozen: Frozen layers\n",
        "# f1: Number of units in dense layer\n",
        "# a1: Activation functions\n",
        "# d1: Drop out\n",
        "# op: Optimizer\n",
        "# ep: Number of epochs\n",
        "\n",
        "#Define VGG19 Model\n",
        "def VGG19_model(frozen, f1, a1, d1, op, ep):\n",
        "  model_fine_tune = VGG19(include_top=False, weights='imagenet', input_shape=input_shape)\n",
        "  for layer in model_fine_tune.layers[:frozen]:          \n",
        "      layer.trainable = False\n",
        "  for layer in model_fine_tune.layers[frozen:]:\n",
        "      layer.trainable = True\n",
        "  model = GlobalAveragePooling2D()(model_fine_tune.output)\n",
        "  model=Dense(units=f1,activation=a1)(model)       \n",
        "  model=Dropout(d1)(model)                             \n",
        "  model = Dense(num_class, activation='softmax')(model)\n",
        "  model = Model(model_fine_tune.input, model, name='vgg')\n",
        "  model.compile(loss='categorical_crossentropy',optimizer=op,metrics=['accuracy'])\n",
        "  es = EarlyStopping(monitor=\"val_accuracy\", patience = 4)\n",
        "  model.fit(train_generator,steps_per_epoch=len(train_generator),epochs=ep,validation_data=validation_generator,\n",
        "            validation_steps=len(validation_generator), callbacks=[es], verbose=0)\n",
        "  return model"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "RZjQTIYsq6RI"
      },
      "outputs": [],
      "source": [
        "from random import choice\n",
        "from random import uniform\n",
        "from numpy.random import randint"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "rqklJUv8q6RJ"
      },
      "outputs": [],
      "source": [
        "def initialization_vgg19():  \n",
        "  parameters = {}\n",
        "  frozen = choice(range(10, 25, 1))\n",
        "  parameters[\"frozen\"] = frozen\n",
        "  f1 = choice([128, 256])\n",
        "  parameters[\"f1\"] = f1\n",
        "  a1 = choice([\"relu\", \"selu\", \"elu\"])\n",
        "  parameters[\"a1\"] = a1\n",
        "  d1 = round(uniform(0.1, 0.6), 1)\n",
        "  parameters[\"d1\"] = d1\n",
        "  op = choice([\"adam\", \"nadam\", \"adamax\", \"adagrad\"])\n",
        "  parameters[\"op\"] = op\n",
        "  ep = randint(10, 25)\n",
        "  parameters[\"ep\"] = ep\n",
        "  return parameters"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "E0eRgP5Nq6RJ"
      },
      "outputs": [],
      "source": [
        "def generate_population_vgg19(n):\n",
        "  population = []\n",
        "  for i in range(n):\n",
        "    chromosome = initialization_vgg19()\n",
        "    population.append(chromosome)\n",
        "  return population"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "fdDggk6-q6RJ"
      },
      "outputs": [],
      "source": [
        "# Fitness evaluation metric: Classification Accuracy \n",
        "def fitness_evaluation(model):\n",
        "  metrics = model.evaluate(validation_generator)\n",
        "  return metrics[1]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "qe1qrrNfq6RJ"
      },
      "outputs": [],
      "source": [
        "# Roulette wheel selection method\n",
        "def selection(population_fitness):\n",
        "  total = sum(population_fitness)\n",
        "  percentage = [round((x/total) * 100) for x in population_fitness]\n",
        "  selection_wheel = []\n",
        "  for pop_index,num in enumerate(percentage):\n",
        "    selection_wheel.extend([pop_index]*num)\n",
        "  parent1_ind = choice(selection_wheel)\n",
        "  parent2_ind = choice(selection_wheel)\n",
        "  return [parent1_ind, parent2_ind]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "o4zhz-c7q6RJ"
      },
      "outputs": [],
      "source": [
        "def crossover_vgg19(parent1, parent2):\n",
        "  child1 = {}\n",
        "  child2 = {}\n",
        "\n",
        "  child1[\"frozen\"] = choice([parent1[\"frozen\"], parent2[\"frozen\"]])\n",
        "  child2[\"frozen\"] = choice([parent1[\"frozen\"], parent2[\"frozen\"]])\n",
        "\n",
        "  child1[\"f1\"] = choice([parent1[\"f1\"], parent2[\"f1\"]])\n",
        "  child2[\"f1\"] = choice([parent1[\"f1\"], parent2[\"f1\"]])\n",
        "\n",
        "  child1[\"a1\"] = parent2[\"a1\"]\n",
        "  child2[\"a1\"] = parent1[\"a1\"]\n",
        "\n",
        "  child1[\"d1\"] = parent1[\"d1\"]\n",
        "  child2[\"d1\"] = parent2[\"d1\"]\n",
        "\n",
        "  child1[\"op\"] = parent1[\"op\"]\n",
        "  child2[\"op\"] = parent2[\"op\"]\n",
        "\n",
        "  child1[\"ep\"] = parent1[\"ep\"]\n",
        "  child2[\"ep\"] = parent2[\"ep\"]\n",
        "  return [child1, child2]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Z_O4Ls--q6RJ"
      },
      "outputs": [],
      "source": [
        "def mutation_vgg19(chromosome):\n",
        "  flag = randint(0,40)\n",
        "  if flag <= 20:\n",
        "    chromosome[\"ep\"] += randint(0, 10)\n",
        "  return chromosome"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "ztuU7YnEq6RJ",
        "outputId": "9c27ab5e-f66b-4cbf-c663-09dac50250f4"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/vgg19/vgg19_weights_tf_dim_ordering_tf_kernels_notop.h5\n",
            "80134624/80134624 [==============================] - 3s 0us/step\n",
            "42/42 [==============================] - 8s 182ms/step - loss: 0.0089 - accuracy: 0.9963\n",
            "Parameters:  {'frozen': 10, 'f1': 128, 'a1': 'relu', 'd1': 0.3, 'op': 'adamax', 'ep': 16}\n",
            "Accuracy:  0.99627\n",
            "42/42 [==============================] - 8s 182ms/step - loss: 0.0089 - accuracy: 0.9955\n",
            "Parameters:  {'frozen': 10, 'f1': 256, 'a1': 'selu', 'd1': 0.5, 'op': 'adamax', 'ep': 23}\n",
            "Accuracy:  0.99553\n",
            "42/42 [==============================] - 8s 183ms/step - loss: 0.1062 - accuracy: 0.9627\n",
            "Parameters:  {'frozen': 22, 'f1': 128, 'a1': 'elu', 'd1': 0.5, 'op': 'adamax', 'ep': 20}\n",
            "Accuracy:  0.96274\n",
            "Generation  1  Outcome: \n",
            "Maximum accuracy in generation 1 : 0.9962742328643799\n"
          ]
        }
      ],
      "source": [
        "generations = 5\n",
        "threshold = 90\n",
        "num_pop = 3\n",
        "\n",
        "population = generate_population_vgg19(num_pop)\n",
        "\n",
        "for generation in range(generations):\n",
        "\n",
        "  population_fitness = []\n",
        "  for chromosome in population:\n",
        "    frozen = chromosome[\"frozen\"]\n",
        "    f1 = chromosome[\"f1\"]\n",
        "    a1 = chromosome[\"a1\"]\n",
        "    d1 = chromosome[\"d1\"]\n",
        "    op = chromosome[\"op\"]\n",
        "    ep = chromosome[\"ep\"]\n",
        "\n",
        "    try:\n",
        "      model = VGG19_model(frozen, f1, a1, d1, op, ep)\n",
        "      acc = fitness_evaluation(model)\n",
        "      print(\"Parameters: \", chromosome)\n",
        "      print(\"Accuracy: \", round(acc,5))\n",
        "    except:\n",
        "      acc=0\n",
        "      print(\"Parameters: \", chromosome)\n",
        "      print(\"Invalid parameters - Build fail\")\n",
        "\n",
        "    population_fitness.append(acc)\n",
        "    \n",
        "  parents_ind = selection(population_fitness)\n",
        "  parent1 = population[parents_ind[0]]\n",
        "  parent2 = population[parents_ind[1]]\n",
        "\n",
        "  children = crossover_vgg19(parent1, parent2)\n",
        "  child1 = mutation_vgg19(children[0])\n",
        "  child2 = mutation_vgg19(children[1])\n",
        "\n",
        "  population.append(child1)\n",
        "  population.append(child2)\n",
        "\n",
        "  print(\"Generation \", generation+1,\" Outcome: \")\n",
        "  if max(population_fitness) >= threshold:\n",
        "    print(\"Obtained desired accuracy: \", max(population_fitness))\n",
        "    break\n",
        "  else:\n",
        "    print(\"Maximum accuracy in generation {} : {}\".format(generation+1, max(population_fitness)))\n",
        "\n",
        "  first_min = min(population_fitness)\n",
        "  first_min_ind = population_fitness.index(first_min)\n",
        "  population.remove(population[first_min_ind])\n",
        "  second_min = min(population_fitness)\n",
        "  second_min_ind = population_fitness.index(second_min)\n",
        "  population.remove(population[second_min_ind])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "oRFN11lxorkM"
      },
      "source": [
        "**Tuning of Inception Model**"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "B4YcoDfworkN"
      },
      "outputs": [],
      "source": [
        "from keras.applications.inception_v3 import InceptionV3"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "0CMsZbykorkN"
      },
      "outputs": [],
      "source": [
        "#Hyperparameters\n",
        "# frozen: Frozen layers\n",
        "# f1: Number of units in dense layer\n",
        "# a1: Activation functions\n",
        "# d1: Drop out\n",
        "# op: Optimizer\n",
        "# ep: Number of epochs\n",
        "\n",
        "#Define Inception Model\n",
        "def Inception_model(frozen, f1, a1, d1, op, ep):\n",
        "  model_fine_tune = InceptionV3(include_top=False, weights='imagenet', input_shape=input_shape)\n",
        "  for layer in model_fine_tune.layers[:frozen]:          \n",
        "      layer.trainable = False\n",
        "  for layer in model_fine_tune.layers[frozen:]:\n",
        "      layer.trainable = True\n",
        "  model = GlobalAveragePooling2D()(model_fine_tune.output)\n",
        "  model=Dense(units=f1,activation=a1)(model)       \n",
        "  model=Dropout(d1)(model)                             \n",
        "  model = Dense(num_class, activation='softmax')(model)\n",
        "  model = Model(model_fine_tune.input, model, name='resnet')\n",
        "  model.compile(loss='categorical_crossentropy',optimizer=op,metrics=['accuracy'])\n",
        "  es = EarlyStopping(monitor=\"val_accuracy\", patience = 4)\n",
        "  model.fit(train_generator,steps_per_epoch=len(train_generator),epochs=ep,validation_data=validation_generator,\n",
        "            validation_steps=len(validation_generator), callbacks=[es], verbose=0)\n",
        "  return model"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "gKc28GMtorkN"
      },
      "outputs": [],
      "source": [
        "from random import choice\n",
        "from random import uniform\n",
        "from numpy.random import randint"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "763a_g8yorkN"
      },
      "outputs": [],
      "source": [
        "def initialization_inception():  \n",
        "  parameters = {}\n",
        "  frozen = choice(range(30, 50, 1))\n",
        "  parameters[\"frozen\"] = frozen\n",
        "  f1 = choice([128, 256])\n",
        "  parameters[\"f1\"] = f1\n",
        "  a1 = choice([\"relu\", \"selu\", \"elu\"])\n",
        "  parameters[\"a1\"] = a1\n",
        "  d1 = round(uniform(0.1, 0.6), 1)\n",
        "  parameters[\"d1\"] = d1\n",
        "  op = choice([\"adam\", \"nadam\", \"adamax\", \"adagrad\"])\n",
        "  parameters[\"op\"] = op\n",
        "  ep = randint(10, 25)\n",
        "  parameters[\"ep\"] = ep\n",
        "  return parameters"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "A4OzP28MorkN"
      },
      "outputs": [],
      "source": [
        "def generate_population_inception(n):\n",
        "  population = []\n",
        "  for i in range(n):\n",
        "    chromosome = initialization_inception()\n",
        "    population.append(chromosome)\n",
        "  return population"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "1TvnwHUAorkN"
      },
      "outputs": [],
      "source": [
        "# Fitness evaluation metric: Classification Accuracy \n",
        "def fitness_evaluation(model):\n",
        "  metrics = model.evaluate(validation_generator)\n",
        "  return metrics[1]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "dT-k2GD5orkN"
      },
      "outputs": [],
      "source": [
        "# Roulette wheel selection method\n",
        "def selection(population_fitness):\n",
        "  total = sum(population_fitness)\n",
        "  percentage = [round((x/total) * 100) for x in population_fitness]\n",
        "  selection_wheel = []\n",
        "  for pop_index,num in enumerate(percentage):\n",
        "    selection_wheel.extend([pop_index]*num)\n",
        "  parent1_ind = choice(selection_wheel)\n",
        "  parent2_ind = choice(selection_wheel)\n",
        "  return [parent1_ind, parent2_ind]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "3YqtpgPzorkO"
      },
      "outputs": [],
      "source": [
        "def crossover_inception(parent1, parent2):\n",
        "  child1 = {}\n",
        "  child2 = {}\n",
        "\n",
        "  child1[\"frozen\"] = choice([parent1[\"frozen\"], parent2[\"frozen\"]])\n",
        "  child2[\"frozen\"] = choice([parent1[\"frozen\"], parent2[\"frozen\"]])\n",
        "\n",
        "  child1[\"f1\"] = choice([parent1[\"f1\"], parent2[\"f1\"]])\n",
        "  child2[\"f1\"] = choice([parent1[\"f1\"], parent2[\"f1\"]])\n",
        "\n",
        "  child1[\"a1\"] = parent2[\"a1\"]\n",
        "  child2[\"a1\"] = parent1[\"a1\"]\n",
        "\n",
        "  child1[\"d1\"] = parent1[\"d1\"]\n",
        "  child2[\"d1\"] = parent2[\"d1\"]\n",
        "\n",
        "  child1[\"op\"] = parent1[\"op\"]\n",
        "  child2[\"op\"] = parent2[\"op\"]\n",
        "\n",
        "  child1[\"ep\"] = parent1[\"ep\"]\n",
        "  child2[\"ep\"] = parent2[\"ep\"]\n",
        "  return [child1, child2]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "2O4QtjvMorkO"
      },
      "outputs": [],
      "source": [
        "def mutation_inception(chromosome):\n",
        "  flag = randint(0,40)\n",
        "  if flag <= 20:\n",
        "    chromosome[\"ep\"] += randint(0, 10)\n",
        "  return chromosome"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "qEDHKFwxorkO",
        "outputId": "8b6dbac4-ba12-4d7c-d3a0-d982209aabe4"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/inception_v3/inception_v3_weights_tf_dim_ordering_tf_kernels_notop.h5\n",
            "87910968/87910968 [==============================] - 3s 0us/step\n",
            "42/42 [==============================] - 4s 100ms/step - loss: 0.0028 - accuracy: 0.9993\n",
            "Parameters:  {'frozen': 45, 'f1': 128, 'a1': 'relu', 'd1': 0.5, 'op': 'adagrad', 'ep': 19}\n",
            "Accuracy:  0.99925\n",
            "42/42 [==============================] - 4s 98ms/step - loss: 0.0122 - accuracy: 0.9940\n",
            "Parameters:  {'frozen': 35, 'f1': 128, 'a1': 'relu', 'd1': 0.2, 'op': 'adamax', 'ep': 24}\n",
            "Accuracy:  0.99404\n",
            "42/42 [==============================] - 4s 99ms/step - loss: 0.0061 - accuracy: 0.9978\n",
            "Parameters:  {'frozen': 30, 'f1': 256, 'a1': 'relu', 'd1': 0.6, 'op': 'adagrad', 'ep': 17}\n",
            "Accuracy:  0.99776\n",
            "Generation  1  Outcome: \n",
            "Maximum accuracy in generation 1 : 0.9992548227310181\n"
          ]
        }
      ],
      "source": [
        "generations = 5\n",
        "threshold = 90\n",
        "num_pop = 3\n",
        "\n",
        "population = generate_population_inception(num_pop)\n",
        "\n",
        "for generation in range(generations):\n",
        "\n",
        "  population_fitness = []\n",
        "  for chromosome in population:\n",
        "    frozen = chromosome[\"frozen\"]\n",
        "    f1 = chromosome[\"f1\"]\n",
        "    a1 = chromosome[\"a1\"]\n",
        "    d1 = chromosome[\"d1\"]\n",
        "    op = chromosome[\"op\"]\n",
        "    ep = chromosome[\"ep\"]\n",
        "\n",
        "    try:\n",
        "      model = Inception_model(frozen, f1, a1, d1, op, ep)\n",
        "      acc = fitness_evaluation(model)\n",
        "      print(\"Parameters: \", chromosome)\n",
        "      print(\"Accuracy: \", round(acc,5))\n",
        "    except:\n",
        "      acc=0\n",
        "      print(\"Parameters: \", chromosome)\n",
        "      print(\"Invalid parameters - Build fail\")\n",
        "\n",
        "    population_fitness.append(acc)\n",
        "    \n",
        "  parents_ind = selection(population_fitness)\n",
        "  parent1 = population[parents_ind[0]]\n",
        "  parent2 = population[parents_ind[1]]\n",
        "\n",
        "  children = crossover_inception(parent1, parent2)\n",
        "  child1 = mutation_inception(children[0])\n",
        "  child2 = mutation_inception(children[1])\n",
        "\n",
        "  population.append(child1)\n",
        "  population.append(child2)\n",
        "\n",
        "  print(\"Generation \", generation+1,\" Outcome: \")\n",
        "  if max(population_fitness) >= threshold:\n",
        "    print(\"Obtained desired accuracy: \", max(population_fitness))\n",
        "    break\n",
        "  else:\n",
        "    print(\"Maximum accuracy in generation {} : {}\".format(generation+1, max(population_fitness)))\n",
        "\n",
        "  first_min = min(population_fitness)\n",
        "  first_min_ind = population_fitness.index(first_min)\n",
        "  population.remove(population[first_min_ind])\n",
        "  second_min = min(population_fitness)\n",
        "  second_min_ind = population_fitness.index(second_min)\n",
        "  population.remove(population[second_min_ind])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "v_gItRPHqZWg"
      },
      "source": [
        "**Tuning of InceptionResnetV2 Model**"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "sJt_HiVLqRY_"
      },
      "outputs": [],
      "source": [
        "from keras.applications.inception_resnet_v2 import InceptionResNetV2"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "spGCUCgFqRZA"
      },
      "outputs": [],
      "source": [
        "#Hyperparameters\n",
        "# frozen: Frozen layers\n",
        "# f1: Number of units in dense layer\n",
        "# a1: Activation functions\n",
        "# d1: Drop out\n",
        "# op: Optimizer\n",
        "# ep: Number of epochs\n",
        "\n",
        "#Define InceptionResnet Model\n",
        "def InceptionRes_model(frozen, f1, a1, d1, op, ep):\n",
        "  model_fine_tune = InceptionResNetV2(include_top=False, weights='imagenet', input_shape=input_shape)\n",
        "  for layer in model_fine_tune.layers[:frozen]:          \n",
        "      layer.trainable = False\n",
        "  for layer in model_fine_tune.layers[frozen:]:\n",
        "      layer.trainable = True\n",
        "  model = GlobalAveragePooling2D()(model_fine_tune.output)\n",
        "  model=Dense(units=f1,activation=a1)(model)       \n",
        "  model=Dropout(d1)(model)                             \n",
        "  model = Dense(num_class, activation='softmax')(model)\n",
        "  model = Model(model_fine_tune.input, model, name='resnet')\n",
        "  model.compile(loss='categorical_crossentropy',optimizer=op,metrics=['accuracy'])\n",
        "  es = EarlyStopping(monitor=\"val_accuracy\", patience = 4)\n",
        "  model.fit(train_generator,steps_per_epoch=len(train_generator),epochs=ep,validation_data=validation_generator,\n",
        "            validation_steps=len(validation_generator), callbacks=[es], verbose=0)\n",
        "  return model"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "uIwnl-6oqRZA"
      },
      "outputs": [],
      "source": [
        "from random import choice\n",
        "from random import uniform\n",
        "from numpy.random import randint"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Gpu3rIX2qRZA"
      },
      "outputs": [],
      "source": [
        "def initialization_IncepRes():  \n",
        "  parameters = {}\n",
        "  frozen = choice(range(400, 600, 1))\n",
        "  parameters[\"frozen\"] = frozen\n",
        "  f1 = choice([128, 256])\n",
        "  parameters[\"f1\"] = f1\n",
        "  a1 = choice([\"relu\", \"selu\", \"elu\"])\n",
        "  parameters[\"a1\"] = a1\n",
        "  d1 = round(uniform(0.1, 0.6), 1)\n",
        "  parameters[\"d1\"] = d1\n",
        "  op = choice([\"adam\", \"nadam\", \"adamax\", \"adagrad\"])\n",
        "  parameters[\"op\"] = op\n",
        "  ep = randint(10, 25)\n",
        "  parameters[\"ep\"] = ep\n",
        "  return parameters"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "dh6k4rdnqRZA"
      },
      "outputs": [],
      "source": [
        "def generate_population_IncepRes(n):\n",
        "  population = []\n",
        "  for i in range(n):\n",
        "    chromosome = initialization_IncepRes()\n",
        "    population.append(chromosome)\n",
        "  return population"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "QlFB7PY8qRZA"
      },
      "outputs": [],
      "source": [
        "# Fitness evaluation metric: Classification Accuracy \n",
        "def fitness_evaluation(model):\n",
        "  metrics = model.evaluate(validation_generator)\n",
        "  return metrics[1]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "MdGZg41SqRZA"
      },
      "outputs": [],
      "source": [
        "# Roulette wheel selection method\n",
        "def selection(population_fitness):\n",
        "  total = sum(population_fitness)\n",
        "  percentage = [round((x/total) * 100) for x in population_fitness]\n",
        "  selection_wheel = []\n",
        "  for pop_index,num in enumerate(percentage):\n",
        "    selection_wheel.extend([pop_index]*num)\n",
        "  parent1_ind = choice(selection_wheel)\n",
        "  parent2_ind = choice(selection_wheel)\n",
        "  return [parent1_ind, parent2_ind]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Z9J3HAeEqRZA"
      },
      "outputs": [],
      "source": [
        "def crossover_IncepRes(parent1, parent2):\n",
        "  child1 = {}\n",
        "  child2 = {}\n",
        "\n",
        "  child1[\"frozen\"] = choice([parent1[\"frozen\"], parent2[\"frozen\"]])\n",
        "  child2[\"frozen\"] = choice([parent1[\"frozen\"], parent2[\"frozen\"]])\n",
        "\n",
        "  child1[\"f1\"] = choice([parent1[\"f1\"], parent2[\"f1\"]])\n",
        "  child2[\"f1\"] = choice([parent1[\"f1\"], parent2[\"f1\"]])\n",
        "\n",
        "  child1[\"a1\"] = parent2[\"a1\"]\n",
        "  child2[\"a1\"] = parent1[\"a1\"]\n",
        "\n",
        "  child1[\"d1\"] = parent1[\"d1\"]\n",
        "  child2[\"d1\"] = parent2[\"d1\"]\n",
        "\n",
        "  child1[\"op\"] = parent1[\"op\"]\n",
        "  child2[\"op\"] = parent2[\"op\"]\n",
        "\n",
        "  child1[\"ep\"] = parent1[\"ep\"]\n",
        "  child2[\"ep\"] = parent2[\"ep\"]\n",
        "  return [child1, child2]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "AkgKyNweqRZB"
      },
      "outputs": [],
      "source": [
        "def mutation_IncepRes(chromosome):\n",
        "  flag = randint(0,40)\n",
        "  if flag <= 20:\n",
        "    chromosome[\"ep\"] += randint(0, 10)\n",
        "  return chromosome"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "AV8TkfzeqRZB",
        "outputId": "e4c3c6ff-6ff4-472c-d848-743bbfc93510"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/inception_resnet_v2/inception_resnet_v2_weights_tf_dim_ordering_tf_kernels_notop.h5\n",
            "219055592/219055592 [==============================] - 11s 0us/step\n",
            "42/42 [==============================] - 8s 180ms/step - loss: 0.0052 - accuracy: 0.9978\n",
            "Parameters:  {'frozen': 451, 'f1': 128, 'a1': 'selu', 'd1': 0.3, 'op': 'adamax', 'ep': 12}\n",
            "Accuracy:  0.99776\n",
            "42/42 [==============================] - 8s 177ms/step - loss: 0.0112 - accuracy: 0.9955\n",
            "Parameters:  {'frozen': 408, 'f1': 256, 'a1': 'selu', 'd1': 0.2, 'op': 'adamax', 'ep': 12}\n",
            "Accuracy:  0.99553\n",
            "42/42 [==============================] - 8s 178ms/step - loss: 0.2455 - accuracy: 0.9620\n",
            "Parameters:  {'frozen': 567, 'f1': 256, 'a1': 'relu', 'd1': 0.4, 'op': 'adam', 'ep': 24}\n",
            "Accuracy:  0.962\n",
            "Generation  1  Outcome: \n",
            "Maximum accuracy in generation 1 : 0.997764527797699\n"
          ]
        }
      ],
      "source": [
        "generations = 5\n",
        "threshold = 90\n",
        "num_pop = 3\n",
        "\n",
        "population = generate_population_IncepRes(num_pop)\n",
        "\n",
        "for generation in range(generations):\n",
        "\n",
        "  population_fitness = []\n",
        "  for chromosome in population:\n",
        "    frozen = chromosome[\"frozen\"]\n",
        "    f1 = chromosome[\"f1\"]\n",
        "    a1 = chromosome[\"a1\"]\n",
        "    d1 = chromosome[\"d1\"]\n",
        "    op = chromosome[\"op\"]\n",
        "    ep = chromosome[\"ep\"]\n",
        "\n",
        "    try:\n",
        "      model = InceptionRes_model(frozen, f1, a1, d1, op, ep)\n",
        "      acc = fitness_evaluation(model)\n",
        "      print(\"Parameters: \", chromosome)\n",
        "      print(\"Accuracy: \", round(acc,5))\n",
        "    except:\n",
        "      acc=0\n",
        "      print(\"Parameters: \", chromosome)\n",
        "      print(\"Invalid parameters - Build fail\")\n",
        "\n",
        "    population_fitness.append(acc)\n",
        "    \n",
        "  parents_ind = selection(population_fitness)\n",
        "  parent1 = population[parents_ind[0]]\n",
        "  parent2 = population[parents_ind[1]]\n",
        "\n",
        "  children = crossover_IncepRes(parent1, parent2)\n",
        "  child1 = mutation_IncepRes(children[0])\n",
        "  child2 = mutation_IncepRes(children[1])\n",
        "\n",
        "  population.append(child1)\n",
        "  population.append(child2)\n",
        "\n",
        "  print(\"Generation \", generation+1,\" Outcome: \")\n",
        "  if max(population_fitness) >= threshold:\n",
        "    print(\"Obtained desired accuracy: \", max(population_fitness))\n",
        "    break\n",
        "  else:\n",
        "    print(\"Maximum accuracy in generation {} : {}\".format(generation+1, max(population_fitness)))\n",
        "\n",
        "  first_min = min(population_fitness)\n",
        "  first_min_ind = population_fitness.index(first_min)\n",
        "  population.remove(population[first_min_ind])\n",
        "  second_min = min(population_fitness)\n",
        "  second_min_ind = population_fitness.index(second_min)\n",
        "  population.remove(population[second_min_ind])"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Ti9h_ss_s0sB"
      },
      "outputs": [],
      "source": []
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "gXvpQiZQs0_4"
      },
      "source": [
        "**Tuning of EfficientNetB7 Model**"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "xYqprFg2s0_4"
      },
      "outputs": [],
      "source": [
        "from keras.applications.efficientnet import EfficientNetB7"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "O3dZJ48ks0_4"
      },
      "outputs": [],
      "source": [
        "#Hyperparameters\n",
        "# frozen: Frozen layers\n",
        "# f1: Number of units in dense layer\n",
        "# a1: Activation functions\n",
        "# d1: Drop out\n",
        "# op: Optimizer\n",
        "# ep: Number of epochs\n",
        "\n",
        "#Define EfficientNetB7 Model\n",
        "def EfficientNetB7_model(frozen, f1, a1, d1, op, ep):\n",
        "  model_fine_tune = EfficientNetB7(include_top=False, weights='imagenet', input_shape=input_shape)\n",
        "  for layer in model_fine_tune.layers[:frozen]:          \n",
        "      layer.trainable = False\n",
        "  for layer in model_fine_tune.layers[frozen:]:\n",
        "      layer.trainable = True\n",
        "  model = GlobalAveragePooling2D()(model_fine_tune.output)\n",
        "  model=Dense(units=f1,activation=a1)(model)       \n",
        "  model=Dropout(d1)(model)                             \n",
        "  model = Dense(num_class, activation='softmax')(model)\n",
        "  model = Model(model_fine_tune.input, model, name='efficientnetb7')\n",
        "  model.compile(loss='categorical_crossentropy',optimizer=op,metrics=['accuracy'])\n",
        "  es = EarlyStopping(monitor=\"val_accuracy\", patience = 4)\n",
        "  model.fit(train_generator,steps_per_epoch=len(train_generator),epochs=ep,validation_data=validation_generator,\n",
        "            validation_steps=len(validation_generator), callbacks=[es], verbose=0)\n",
        "  return model"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "Fv7qjTMDs0_4"
      },
      "outputs": [],
      "source": [
        "from random import choice\n",
        "from random import uniform\n",
        "from numpy.random import randint"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "BuOTr5TEs0_4"
      },
      "outputs": [],
      "source": [
        "def initialization_EfficientNetB7():  \n",
        "  parameters = {}\n",
        "  frozen = choice(range(270, 350, 1))\n",
        "  parameters[\"frozen\"] = frozen\n",
        "  f1 = choice([128, 256])\n",
        "  parameters[\"f1\"] = f1\n",
        "  a1 = choice([\"relu\", \"selu\", \"elu\"])\n",
        "  parameters[\"a1\"] = a1\n",
        "  d1 = round(uniform(0.1, 0.6), 1)\n",
        "  parameters[\"d1\"] = d1\n",
        "  op = choice([\"adam\", \"nadam\", \"adamax\", \"adagrad\"])\n",
        "  parameters[\"op\"] = op\n",
        "  ep = randint(10, 25)\n",
        "  parameters[\"ep\"] = ep\n",
        "  return parameters"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "XfBFnzvfs0_5"
      },
      "outputs": [],
      "source": [
        "def generate_population_EfficientNetB7(n):\n",
        "  population = []\n",
        "  for i in range(n):\n",
        "    chromosome = initialization_EfficientNetB7()\n",
        "    population.append(chromosome)\n",
        "  return population"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "pO4Sa4BAs0_5"
      },
      "outputs": [],
      "source": [
        "# Fitness evaluation metric: Classification Accuracy \n",
        "def fitness_evaluation(model):\n",
        "  metrics = model.evaluate(validation_generator)\n",
        "  return metrics[1]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "bqxTMOFgs0_5"
      },
      "outputs": [],
      "source": [
        "# Roulette wheel selection method\n",
        "def selection(population_fitness):\n",
        "  total = sum(population_fitness)\n",
        "  percentage = [round((x/total) * 100) for x in population_fitness]\n",
        "  selection_wheel = []\n",
        "  for pop_index,num in enumerate(percentage):\n",
        "    selection_wheel.extend([pop_index]*num)\n",
        "  parent1_ind = choice(selection_wheel)\n",
        "  parent2_ind = choice(selection_wheel)\n",
        "  return [parent1_ind, parent2_ind]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "sGGbAo93s0_5"
      },
      "outputs": [],
      "source": [
        "def crossover_EfficientNetB7(parent1, parent2):\n",
        "  child1 = {}\n",
        "  child2 = {}\n",
        "\n",
        "  child1[\"frozen\"] = choice([parent1[\"frozen\"], parent2[\"frozen\"]])\n",
        "  child2[\"frozen\"] = choice([parent1[\"frozen\"], parent2[\"frozen\"]])\n",
        "\n",
        "  child1[\"f1\"] = choice([parent1[\"f1\"], parent2[\"f1\"]])\n",
        "  child2[\"f1\"] = choice([parent1[\"f1\"], parent2[\"f1\"]])\n",
        "\n",
        "  child1[\"a1\"] = parent2[\"a1\"]\n",
        "  child2[\"a1\"] = parent1[\"a1\"]\n",
        "\n",
        "  child1[\"d1\"] = parent1[\"d1\"]\n",
        "  child2[\"d1\"] = parent2[\"d1\"]\n",
        "\n",
        "  child1[\"op\"] = parent1[\"op\"]\n",
        "  child2[\"op\"] = parent2[\"op\"]\n",
        "\n",
        "  child1[\"ep\"] = parent1[\"ep\"]\n",
        "  child2[\"ep\"] = parent2[\"ep\"]\n",
        "  return [child1, child2]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "UfwofpPps0_5"
      },
      "outputs": [],
      "source": [
        "def mutation_EfficientNetB7(chromosome):\n",
        "  flag = randint(0,40)\n",
        "  if flag <= 20:\n",
        "    chromosome[\"ep\"] += randint(0, 10)\n",
        "  return chromosome"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "base_uri": "https://localhost:8080/"
        },
        "id": "kehrEwz1s0_5",
        "outputId": "aa748a3d-e450-4a5f-98e1-a45b943e05de"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Downloading data from https://storage.googleapis.com/keras-applications/efficientnetb7_notop.h5\n",
            "258076736/258076736 [==============================] - 10s 0us/step\n",
            "42/42 [==============================] - 15s 355ms/step - loss: 0.0643 - accuracy: 0.9709\n",
            "Parameters:  {'frozen': 302, 'f1': 256, 'a1': 'elu', 'd1': 0.2, 'op': 'nadam', 'ep': 18}\n",
            "Accuracy:  0.97094\n",
            "42/42 [==============================] - 15s 355ms/step - loss: 0.1417 - accuracy: 0.9687\n",
            "Parameters:  {'frozen': 285, 'f1': 128, 'a1': 'selu', 'd1': 0.2, 'op': 'adamax', 'ep': 18}\n",
            "Accuracy:  0.9687\n",
            "42/42 [==============================] - 15s 355ms/step - loss: 0.0952 - accuracy: 0.9694\n",
            "Parameters:  {'frozen': 288, 'f1': 128, 'a1': 'selu', 'd1': 0.4, 'op': 'adam', 'ep': 15}\n",
            "Accuracy:  0.96945\n",
            "Generation  1  Outcome: \n",
            "Maximum accuracy in generation 1 : 0.9709389209747314\n",
            "42/42 [==============================] - 15s 355ms/step - loss: 13.8226 - accuracy: 0.0380\n",
            "Parameters:  {'frozen': 302, 'f1': 256, 'a1': 'elu', 'd1': 0.2, 'op': 'nadam', 'ep': 18}\n",
            "Accuracy:  0.038\n",
            "42/42 [==============================] - 15s 355ms/step - loss: 0.0882 - accuracy: 0.9583\n",
            "Parameters:  {'frozen': 288, 'f1': 128, 'a1': 'selu', 'd1': 0.4, 'op': 'adam', 'ep': 18}\n",
            "Accuracy:  0.95827\n",
            "42/42 [==============================] - 15s 355ms/step - loss: 0.0546 - accuracy: 0.9657\n",
            "Parameters:  {'frozen': 288, 'f1': 128, 'a1': 'selu', 'd1': 0.4, 'op': 'adam', 'ep': 15}\n",
            "Accuracy:  0.96572\n",
            "Generation  2  Outcome: \n",
            "Maximum accuracy in generation 2 : 0.9657227993011475\n",
            "42/42 [==============================] - 15s 354ms/step - loss: 0.0449 - accuracy: 0.9806\n",
            "Parameters:  {'frozen': 288, 'f1': 128, 'a1': 'selu', 'd1': 0.4, 'op': 'adam', 'ep': 15}\n",
            "Accuracy:  0.98063\n",
            "42/42 [==============================] - 15s 354ms/step - loss: 0.0618 - accuracy: 0.9709\n",
            "Parameters:  {'frozen': 288, 'f1': 128, 'a1': 'selu', 'd1': 0.4, 'op': 'adam', 'ep': 16}\n",
            "Accuracy:  0.97094\n",
            "42/42 [==============================] - 15s 355ms/step - loss: 1.6461 - accuracy: 0.3487\n",
            "Parameters:  {'frozen': 288, 'f1': 128, 'a1': 'selu', 'd1': 0.4, 'op': 'adam', 'ep': 15}\n",
            "Accuracy:  0.34873\n",
            "Generation  3  Outcome: \n",
            "Maximum accuracy in generation 3 : 0.9806259274482727\n",
            "42/42 [==============================] - 15s 354ms/step - loss: 0.0512 - accuracy: 0.9672\n",
            "Parameters:  {'frozen': 288, 'f1': 128, 'a1': 'selu', 'd1': 0.4, 'op': 'adam', 'ep': 16}\n",
            "Accuracy:  0.96721\n",
            "42/42 [==============================] - 15s 355ms/step - loss: 0.1411 - accuracy: 0.9523\n",
            "Parameters:  {'frozen': 288, 'f1': 128, 'a1': 'selu', 'd1': 0.4, 'op': 'adam', 'ep': 15}\n",
            "Accuracy:  0.95231\n",
            "42/42 [==============================] - 15s 355ms/step - loss: 0.0735 - accuracy: 0.9680\n",
            "Parameters:  {'frozen': 288, 'f1': 128, 'a1': 'selu', 'd1': 0.4, 'op': 'adam', 'ep': 20}\n",
            "Accuracy:  0.96796\n",
            "Generation  4  Outcome: \n",
            "Maximum accuracy in generation 4 : 0.9679582715034485\n",
            "42/42 [==============================] - 15s 355ms/step - loss: 0.0705 - accuracy: 0.9724\n",
            "Parameters:  {'frozen': 288, 'f1': 128, 'a1': 'selu', 'd1': 0.4, 'op': 'adam', 'ep': 16}\n",
            "Accuracy:  0.97243\n",
            "42/42 [==============================] - 15s 355ms/step - loss: 0.0502 - accuracy: 0.9776\n",
            "Parameters:  {'frozen': 288, 'f1': 128, 'a1': 'selu', 'd1': 0.4, 'op': 'adam', 'ep': 15}\n",
            "Accuracy:  0.97765\n",
            "42/42 [==============================] - 15s 354ms/step - loss: 0.0514 - accuracy: 0.9747\n",
            "Parameters:  {'frozen': 288, 'f1': 128, 'a1': 'selu', 'd1': 0.4, 'op': 'adam', 'ep': 16}\n",
            "Accuracy:  0.97466\n",
            "Generation  5  Outcome: \n",
            "Maximum accuracy in generation 5 : 0.9776452779769897\n"
          ]
        }
      ],
      "source": [
        "generations = 5\n",
        "threshold = 90\n",
        "num_pop = 3\n",
        "\n",
        "population = generate_population_EfficientNetB7(num_pop)\n",
        "\n",
        "for generation in range(generations):\n",
        "\n",
        "  population_fitness = []\n",
        "  for chromosome in population:\n",
        "    frozen = chromosome[\"frozen\"]\n",
        "    f1 = chromosome[\"f1\"]\n",
        "    a1 = chromosome[\"a1\"]\n",
        "    d1 = chromosome[\"d1\"]\n",
        "    op = chromosome[\"op\"]\n",
        "    ep = chromosome[\"ep\"]\n",
        "\n",
        "    try:\n",
        "      model = EfficientNetB7_model(frozen, f1, a1, d1, op, ep)\n",
        "      acc = fitness_evaluation(model)\n",
        "      print(\"Parameters: \", chromosome)\n",
        "      print(\"Accuracy: \", round(acc,5))\n",
        "    except:\n",
        "      acc=0\n",
        "      print(\"Parameters: \", chromosome)\n",
        "      print(\"Invalid parameters - Build fail\")\n",
        "\n",
        "    population_fitness.append(acc)\n",
        "    \n",
        "  parents_ind = selection(population_fitness)\n",
        "  parent1 = population[parents_ind[0]]\n",
        "  parent2 = population[parents_ind[1]]\n",
        "\n",
        "  children = crossover_EfficientNetB7(parent1, parent2)\n",
        "  child1 = mutation_EfficientNetB7(children[0])\n",
        "  child2 = mutation_EfficientNetB7(children[1])\n",
        "\n",
        "  population.append(child1)\n",
        "  population.append(child2)\n",
        "\n",
        "  print(\"Generation \", generation+1,\" Outcome: \")\n",
        "  if max(population_fitness) >= threshold:\n",
        "    print(\"Obtained desired accuracy: \", max(population_fitness))\n",
        "    break\n",
        "  else:\n",
        "    print(\"Maximum accuracy in generation {} : {}\".format(generation+1, max(population_fitness)))\n",
        "\n",
        "  first_min = min(population_fitness)\n",
        "  first_min_ind = population_fitness.index(first_min)\n",
        "  population.remove(population[first_min_ind])\n",
        "  second_min = min(population_fitness)\n",
        "  second_min_ind = population_fitness.index(second_min)\n",
        "  population.remove(population[second_min_ind])"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "YLZTqZreu-D5"
      },
      "source": [
        "**Tuning of EfficientNetV2L Model**"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "c6Mcz8tpu-D5"
      },
      "outputs": [],
      "source": [
        "from keras.applications.efficientnet_v2 import EfficientNetV2L"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "RyAHx84ku-D5"
      },
      "outputs": [],
      "source": [
        "#Hyperparameters\n",
        "# frozen: Frozen layers\n",
        "# f1: Number of units in dense layer\n",
        "# a1: Activation functions\n",
        "# d1: Drop out\n",
        "# op: Optimizer\n",
        "# ep: Number of epochs\n",
        "\n",
        "#Define EfficientNetV2L Model\n",
        "def EfficientNetV2L_model(frozen, f1, a1, d1, op, ep):\n",
        "  model_fine_tune = EfficientNetV2L(include_top=False, weights='imagenet', input_shape=input_shape)\n",
        "  for layer in model_fine_tune.layers[:frozen]:          \n",
        "      layer.trainable = False\n",
        "  for layer in model_fine_tune.layers[frozen:]:\n",
        "      layer.trainable = True\n",
        "  model = GlobalAveragePooling2D()(model_fine_tune.output)\n",
        "  model=Dense(units=f1,activation=a1)(model)       \n",
        "  model=Dropout(d1)(model)                             \n",
        "  model = Dense(num_class, activation='softmax')(model)\n",
        "  model = Model(model_fine_tune.input, model, name='efficientnetv2-l')\n",
        "  model.compile(loss='categorical_crossentropy',optimizer=op,metrics=['accuracy'])\n",
        "  es = EarlyStopping(monitor=\"val_accuracy\", patience = 4)\n",
        "  model.fit(train_generator,steps_per_epoch=len(train_generator),epochs=ep,validation_data=validation_generator,\n",
        "            validation_steps=len(validation_generator), callbacks=[es], verbose=0)\n",
        "  return model"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "ytjWAiteu-D6"
      },
      "outputs": [],
      "source": [
        "from random import choice\n",
        "from random import uniform\n",
        "from numpy.random import randint"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "CNBJuryCu-D6"
      },
      "outputs": [],
      "source": [
        "def initialization_EfficientNetV2L():  \n",
        "  parameters = {}\n",
        "  frozen = choice(range(380, 430, 1))\n",
        "  parameters[\"frozen\"] = frozen\n",
        "  f1 = choice([128, 256])\n",
        "  parameters[\"f1\"] = f1\n",
        "  a1 = choice([\"relu\", \"selu\", \"elu\"])\n",
        "  parameters[\"a1\"] = a1\n",
        "  d1 = round(uniform(0.1, 0.6), 1)\n",
        "  parameters[\"d1\"] = d1\n",
        "  op = choice([\"adam\", \"nadam\", \"adamax\", \"adagrad\"])\n",
        "  parameters[\"op\"] = op\n",
        "  ep = randint(10, 25)\n",
        "  parameters[\"ep\"] = ep\n",
        "  return parameters"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "9i_7Nssfu-D6"
      },
      "outputs": [],
      "source": [
        "def generate_population_EfficientNetV2L(n):\n",
        "  population = []\n",
        "  for i in range(n):\n",
        "    chromosome = initialization_EfficientNetV2L()\n",
        "    population.append(chromosome)\n",
        "  return population"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "y8Z7RvTFu-D6"
      },
      "outputs": [],
      "source": [
        "# Fitness evaluation metric: Classification Accuracy \n",
        "def fitness_evaluation(model):\n",
        "  metrics = model.evaluate(validation_generator)\n",
        "  return metrics[1]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "RbmtoB6Wu-D6"
      },
      "outputs": [],
      "source": [
        "# Roulette wheel selection method\n",
        "def selection(population_fitness):\n",
        "  total = sum(population_fitness)\n",
        "  percentage = [round((x/total) * 100) for x in population_fitness]\n",
        "  selection_wheel = []\n",
        "  for pop_index,num in enumerate(percentage):\n",
        "    selection_wheel.extend([pop_index]*num)\n",
        "  parent1_ind = choice(selection_wheel)\n",
        "  parent2_ind = choice(selection_wheel)\n",
        "  return [parent1_ind, parent2_ind]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "zffZIvGru-D6"
      },
      "outputs": [],
      "source": [
        "def crossover_EfficientNetV2L(parent1, parent2):\n",
        "  child1 = {}\n",
        "  child2 = {}\n",
        "\n",
        "  child1[\"frozen\"] = choice([parent1[\"frozen\"], parent2[\"frozen\"]])\n",
        "  child2[\"frozen\"] = choice([parent1[\"frozen\"], parent2[\"frozen\"]])\n",
        "\n",
        "  child1[\"f1\"] = choice([parent1[\"f1\"], parent2[\"f1\"]])\n",
        "  child2[\"f1\"] = choice([parent1[\"f1\"], parent2[\"f1\"]])\n",
        "\n",
        "  child1[\"a1\"] = parent2[\"a1\"]\n",
        "  child2[\"a1\"] = parent1[\"a1\"]\n",
        "\n",
        "  child1[\"d1\"] = parent1[\"d1\"]\n",
        "  child2[\"d1\"] = parent2[\"d1\"]\n",
        "\n",
        "  child1[\"op\"] = parent1[\"op\"]\n",
        "  child2[\"op\"] = parent2[\"op\"]\n",
        "\n",
        "  child1[\"ep\"] = parent1[\"ep\"]\n",
        "  child2[\"ep\"] = parent2[\"ep\"]\n",
        "  return [child1, child2]"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "id": "AonROPVnu-D6"
      },
      "outputs": [],
      "source": [
        "def mutation_EfficientNetV2L(chromosome):\n",
        "  flag = randint(0,40)\n",
        "  if flag <= 20:\n",
        "    chromosome[\"ep\"] += randint(0, 10)\n",
        "  return chromosome"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "colab": {
          "background_save": true,
          "base_uri": "https://localhost:8080/"
        },
        "id": "cwGKv58Qu-D6",
        "outputId": "08d385a5-4731-476a-a11f-e0825a7e0084"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Downloading data from https://storage.googleapis.com/tensorflow/keras-applications/efficientnet_v2/efficientnetv2-l_notop.h5\n",
            "473176280/473176280 [==============================] - 18s 0us/step\n",
            "42/42 [==============================] - 16s 384ms/step - loss: 0.0305 - accuracy: 0.9851\n",
            "Parameters:  {'frozen': 305, 'f1': 256, 'a1': 'selu', 'd1': 0.5, 'op': 'adam', 'ep': 24}\n",
            "Accuracy:  0.9851\n",
            "42/42 [==============================] - 16s 386ms/step - loss: 0.0234 - accuracy: 0.9911\n",
            "Parameters:  {'frozen': 284, 'f1': 256, 'a1': 'selu', 'd1': 0.3, 'op': 'adamax', 'ep': 15}\n",
            "Accuracy:  0.99106\n",
            "42/42 [==============================] - 16s 386ms/step - loss: 0.0212 - accuracy: 0.9918\n",
            "Parameters:  {'frozen': 316, 'f1': 128, 'a1': 'selu', 'd1': 0.5, 'op': 'adam', 'ep': 19}\n",
            "Accuracy:  0.9918\n",
            "Generation  1  Outcome: \n",
            "Maximum accuracy in generation 1 : 0.9918032884597778\n",
            "42/42 [==============================] - 16s 386ms/step - loss: 0.0648 - accuracy: 0.9829\n",
            "Parameters:  {'frozen': 316, 'f1': 128, 'a1': 'selu', 'd1': 0.5, 'op': 'adam', 'ep': 19}\n",
            "Accuracy:  0.98286\n"
          ]
        }
      ],
      "source": [
        "\n",
        "generations = 5\n",
        "threshold = 90\n",
        "num_pop = 3\n",
        "\n",
        "population = generate_population_EfficientNetB7(num_pop)\n",
        "\n",
        "for generation in range(generations):\n",
        "\n",
        "  population_fitness = []\n",
        "  for chromosome in population:\n",
        "    frozen = chromosome[\"frozen\"]\n",
        "    f1 = chromosome[\"f1\"]\n",
        "    a1 = chromosome[\"a1\"]\n",
        "    d1 = chromosome[\"d1\"]\n",
        "    op = chromosome[\"op\"]\n",
        "    ep = chromosome[\"ep\"]\n",
        "\n",
        "    try:\n",
        "      model = EfficientNetV2L_model(frozen, f1, a1, d1, op, ep)\n",
        "      acc = fitness_evaluation(model)\n",
        "      print(\"Parameters: \", chromosome)\n",
        "      print(\"Accuracy: \", round(acc,5))\n",
        "    except:\n",
        "      acc=0\n",
        "      print(\"Parameters: \", chromosome)\n",
        "      print(\"Invalid parameters - Build fail\")\n",
        "\n",
        "    population_fitness.append(acc)\n",
        "    \n",
        "  parents_ind = selection(population_fitness)\n",
        "  parent1 = population[parents_ind[0]]\n",
        "  parent2 = population[parents_ind[1]]\n",
        "\n",
        "  children = crossover_EfficientNetV2L(parent1, parent2)\n",
        "  child1 = mutation_EfficientNetV2L(children[0])\n",
        "  child2 = mutation_EfficientNetV2L(children[1])\n",
        "\n",
        "  population.append(child1)\n",
        "  population.append(child2)\n",
        "\n",
        "  print(\"Generation \", generation+1,\" Outcome: \")\n",
        "  if max(population_fitness) >= threshold:\n",
        "    print(\"Obtained desired accuracy: \", max(population_fitness))\n",
        "    break\n",
        "  else:\n",
        "    print(\"Maximum accuracy in generation {} : {}\".format(generation+1, max(population_fitness)))\n",
        "\n",
        "  first_min = min(population_fitness)\n",
        "  first_min_ind = population_fitness.index(first_min)\n",
        "  population.remove(population[first_min_ind])\n",
        "  second_min = min(population_fitness)\n",
        "  second_min_ind = population_fitness.index(second_min)\n",
        "  population.remove(population[second_min_ind])"
      ]
    }
  ],
  "metadata": {
    "accelerator": "GPU",
    "colab": {
      "machine_shape": "hm",
      "provenance": []
    },
    "gpuClass": "standard",
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    },
    "language_info": {
      "name": "python"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}